﻿using FPDAM.Models;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace TestModule
{
    /// <summary>
    /// 绘图测试接口类，提供基本图形元素的绘制包括：Curve、CurveSegment（直线、圆弧、风螺旋）、Point
    /// </summary>
    public class DrawTool
    {
        private List<NodeSymbol> _nodes = new List<NodeSymbol>();
        private Dictionary<int, object> _curveSet = new Dictionary<int, object>();
        public Dictionary<int, object> CurveSet
        {
            get { return _curveSet; }
            set
            {
                _curveSet = value;
            }
        }

        /// <summary>
        /// GDI绘图工具类
        /// </summary>
        private Graphics _graphicImg = null;
        public DrawTool(Graphics img)
        {
            this._graphicImg = img;
        }

        /// <summary>
        /// 绘制图形集合
        /// </summary>
        /// <param name="CurveSet"></param>
        public void DrawGraphic()
        {
            if (this._curveSet.Count == 0)
                return;

            if (this._nodes.Count == 0)
            {
                this._nodes = ToNodes(_curveSet);
                InitialMapRange();
                this._nodes = MoveTo(new Point { X = this._mapRange.MinAbscissa, Y = this._mapRange.MinOrdinate }, this._nodes);
            }

            foreach (NodeSymbol item in this._nodes)
                item.Draw(this._graphicImg);
        }

        /// <summary>
        /// 放大图形
        /// </summary>
        /// <param name="widenValue"></param>
        public void WidenGraphic(float widenValue)
        {
            if (this._graphicImg == null)
                return;

            this._graphicImg.ScaleTransform(widenValue, widenValue, MatrixOrder.Append);
        }

        /// <summary>
        /// 平移图形
        /// </summary>
        /// <param name="fx"></param>
        /// <param name="fy"></param>
        public void MoveGraphic(float fx, float fy)
        {
            if (this._graphicImg == null)
                return;

            this._graphicImg.TranslateTransform(fx, fy);
        }

        /// <summary>
        /// 设定点样式
        /// </summary>
        /// <param name="type"></param>
        public void SetPointSymbol(PointType type)
        {
            foreach (NodeSymbol item in this._nodes)
            {
                if (item.GetType() == typeof(NodePoint))
                    (item as NodePoint).Symboltype = type;
            }
        }

        /// <summary>
        /// 设置是否显示注释
        /// </summary>
        /// <param name="bRemark"></param>
        public void SetBPointRemark(bool bRemark, Type dataType)
        {
            foreach (NodeSymbol item in this._nodes)
            {
                if (item.GetType() == dataType)
                    item.BRemark = bRemark;
            }
        }

        /// <summary>
        /// 设置是否显示方向
        /// </summary>
        /// <param name="bDirection"></param>
        /// <param name="dataType"></param>
        public void SetLineSymbolDirection(bool bDirection)
        {
            foreach (NodeSymbol item in this._nodes)
            {
                if (item.GetType() == typeof(NodeLine) || item.GetType() == typeof(NodeArc))
                    (item as NodeLineSymbol).BDirection = bDirection;
            }
        }

        /// <summary>
        /// 设置线的宽度
        /// </summary>
        /// <param name="width"></param>
        /// <param name="dataType"></param>
        public void SetLineSymbolWidth(float width)
        {
            foreach (NodeSymbol item in this._nodes)
            {
                if (item.GetType() == typeof(NodeLine) || item.GetType() == typeof(NodeArc))
                    (item as NodeLineSymbol).Width = width;
            }
        }

        /// <summary>
        /// 设置线段颜色
        /// </summary>
        /// <param name="color"></param>
        public void SetLineSymbolColor(Color color)
        {
            foreach (NodeSymbol item in this._nodes)
            {
                if (item.GetType() == typeof(NodeLine) || item.GetType() == typeof(NodeArc))
                    item.PenColor = color;
            }
        }

        /// <summary>
        /// 设置是否显示序号
        /// </summary>
        /// <param name="bIndex"></param>
        /// <param name="dataType"></param>
        public void SetIndex(bool bIndex, Type dataType)
        {
            foreach (NodeSymbol item in this._nodes)
            {
                if (item.GetType() == dataType)
                    item.BNo = bIndex;
            }
        }

        /// <summary>
        /// 清空画布
        /// </summary>
        public void ClearGraphic()
        {
            this._graphicImg.Clear(Color.White);
        }

        #region 数据整理
        private List<NodeSymbol> ToNodes(Dictionary<int, object> CurveSet)
        {
            List<NodeSymbol> nodes = new List<NodeSymbol>();
            foreach (var item in CurveSet)
            {
                if (item.Value.GetType() == typeof(Point3D))
                    nodes.Add(new NodePoint()
                    {
                        Index = item.Key,
                        PenColor = Color.Black,
                        Symboltype = PointType.NORMAL_POINT,
                        Remark = "点",
                        BRemark = true,
                        BasePoint = new Point() { X = Convert.ToInt16((item.Value as Point3D).X), Y = Convert.ToInt16((item.Value as Point3D).Y) }
                    });
                else if (item.Value.GetType() == typeof(LineSegment))
                    nodes.Add(new NodeLine()
                    {
                        Index = item.Key,
                        PenColor = Color.Black,
                        BDirection = true,
                        Remark = "线段",
                        BRemark = true,
                        Width = 1,
                        BeginPoint = new Point() { X = Convert.ToInt16((item.Value as LineSegment).BeginPoint.X), Y = Convert.ToInt16((item.Value as LineSegment).BeginPoint.Y) },
                        EndPoint = new Point() { X = Convert.ToInt16((item.Value as LineSegment).EndPoint.X), Y = Convert.ToInt16((item.Value as LineSegment).EndPoint.Y) }
                    });
                else if (item.Value.GetType() == typeof(ArcSegment))
                    nodes.Add(new NodeArc()
                    {
                        Index = item.Key,
                        PenColor = Color.Black,
                        BDirection = true,
                        Remark = "圆弧",
                        BRemark = true,
                        Width = 1,
                        Center = new Point() { X = Convert.ToInt16((item.Value as ArcSegment).Center.X), Y = Convert.ToInt16((item.Value as ArcSegment).Center.Y) },
                        Radius = (item.Value as ArcSegment).Radius,
                        BeginAngle = (item.Value as ArcSegment).BeginRadian * 180 / Math.PI,
                        EndAngle = (item.Value as ArcSegment).EndRadian * 180 / Math.PI,
                        Arcdir = (item.Value as ArcSegment).ArcDir == ArcDirction.CLOCK_WISE ? 1 : -1
                    });
                else if (item.Value.GetType() == typeof(Curve))
                {
                    Dictionary<int, object> Temp = new Dictionary<int, object>();
                    foreach (var itemTemp in (item.Value as Curve).Segs)
                    {
                        Temp.Add(itemTemp.Key, itemTemp.Value);
                    }

                    nodes.AddRange(ToNodes(Temp));
                }
                else
                    throw new Exception("找不到指定图形数据的转换对象");
            }

            return nodes;
        }

        private MapRange _mapRange = new MapRange();
        private List<Point> _nodePoints = new List<Point>();
        private void InitialMapRange()
        {
            foreach (var node in this._nodes)
            {
                if (node.GetType() == typeof(NodeArc))
                {
                    this._nodePoints.Add(new Point() { 
                        X = (node as NodeArc).Center.X + Convert.ToInt16((node as NodeArc).Radius),
                        Y = (node as NodeArc).Center.Y + Convert.ToInt16((node as NodeArc).Radius)
                    });
                    this._nodePoints.Add(new Point()
                    {
                        X = (node as NodeArc).Center.X - Convert.ToInt16((node as NodeArc).Radius),
                        Y = (node as NodeArc).Center.Y - Convert.ToInt16((node as NodeArc).Radius)
                    });
                }
                else if (node.GetType() == typeof(NodeLine))
                {
                    this._nodePoints.Add((node as NodeLine).BeginPoint);
                    this._nodePoints.Add((node as NodeLine).EndPoint);
                }
                else if (node.GetType() == typeof(NodePoint))
                    this._nodePoints.Add((node as NodePoint).BasePoint);
            }

            int[] abscissaLists = new int[this._nodePoints.Count];
            int[] ordinateLists = new int[this._nodePoints.Count];
            for (int i = 0; i < this._nodePoints.Count; i++)
            {
                abscissaLists[i] = Convert.ToInt32(this._nodePoints[i].X);
                ordinateLists[i] = Convert.ToInt32(this._nodePoints[i].Y);
            }

            this._mapRange.MaxAbscissa = abscissaLists.Max();
            this._mapRange.MinAbscissa = abscissaLists.Min();
            this._mapRange.MaxOrdinate = ordinateLists.Max();
            this._mapRange.MinOrdinate = ordinateLists.Min();
        }

        private List<NodeSymbol> MoveTo(Point point, List<NodeSymbol> nodeList)
        {
            foreach (var item in nodeList)
            {
                if (item.GetType() == typeof(NodePoint))
                    (item as NodePoint).BasePoint = MoveTo(point, (item as NodePoint).BasePoint);
                else if (item.GetType() == typeof(NodeLine))
                {
                    (item as NodeLine).BeginPoint = MoveTo(point, (item as NodeLine).BeginPoint);
                    (item as NodeLine).EndPoint = MoveTo(point, (item as NodeLine).EndPoint);
                }
                else if (item.GetType() == typeof(NodeArc))
                    (item as NodeArc).Center = MoveTo(point, (item as NodeArc).Center);
                else
                    continue;
            }

            return nodeList;
        }

        private Point MoveTo(Point point, Point tempPoint)
        {
            return new Point() { X = tempPoint.X - point.X + 100, Y = tempPoint.Y - point.Y + 100 };
        }
        #endregion

    }
}
